package com.xinhe.web.service;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.xinhe.web.common.Result;
import com.xinhe.web.entity.*;
import com.xinhe.web.reposity.*;
import com.xinhe.web.response.LoginView;
import com.xinhe.web.session.UserSessionManager;
import com.xinhe.web.session.UserSessionView;
import com.xinhe.web.util.Snowflake;
import com.xinhe.web.vo.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.inject.Provider;
import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class LocalUserService {

    //初始化查询工厂
    private JPAQueryFactory queryFactory;
    @Autowired
    private Provider<EntityManager> entityManager;
    @PostConstruct
    public void init() {
        queryFactory = new JPAQueryFactory(entityManager);
    }
    @Autowired
    LocalUserRepository localUserRepository;
    @Autowired
    AuthMenuRepository authMenuRepository;
    @Autowired
    AuthRoleMenuRepository authRoleMenuRepository;
    @Autowired
    AuthRoleRepository authRoleRepository;
    @Autowired
    AuthUserRoleRepository authUserRoleRepository;
    @Autowired
    MenuService menuService;
    @Autowired
    private UserSessionManager sessionManager;
    @Autowired
    private UserService userService;
    @Autowired
    UserRoleService userRoleService;
    @Autowired(required = false)
    private UserSessionManager userSessionManager;

    public QueryResults<LocalUser> findUserInfoByPage(Integer pageNum, Integer pageSize) {
        QLocalUser qLocalUser = QLocalUser.localUser;
        BooleanBuilder builder = new BooleanBuilder();
        OrderSpecifier<Date> sort = qLocalUser.createTime.desc();
        return queryFactory.select(
                Projections.bean(
                        LocalUser.class,
                        qLocalUser.password,
                        qLocalUser.remark.as("remark"),
                        qLocalUser.removed.as("removed"),
                        qLocalUser.username.as("username"),
                        qLocalUser.fUserId.as("fUserId"),
                        qLocalUser.id.as("id"),
                        qLocalUser.versionNum.as("versionNum"),
                        qLocalUser.createTime
                )
        ).from(qLocalUser)
                .where(builder).offset(pageNum * pageSize).limit(pageSize).orderBy(sort).fetchResults();
    }

    public Result<LocalUserView> login(String username, String password) {
        LocalUserView localUserView = new LocalUserView();
        String encodePwd = DigestUtils.md5Hex(password);
        LocalUser localUser = localUserRepository.findByUsernameAndPassword(username, encodePwd);
        if (null == localUser) {
            return Result.failed(1001,"账号或密码错误");
        }
        localUserView.setUserId(localUser.getId());
        localUserView.setUsername(localUser.getUsername());
        localUserView.setIconPath(localUser.getIconPath());
        localUserView.setPassword(localUser.getPassword());
        localUserView.setCreateTime(localUser.getCreateTime());

        List<RoleView> roleViews = new ArrayList<>();//暂时不需要给前端
        //查询用户角色表，捞出角色id。理论上只有一个
        List<UserRole> authUserRoleList = authUserRoleRepository.findAuthUserRoleByUserid(localUser.getId());
        //根据角色id查询具体角色。理论上只有一个
        if (!CollectionUtils.isEmpty(authUserRoleList)){
            List<Role> authRoleList = authRoleRepository.findAuthRoleById(authUserRoleList.get(0).getRoleId());
            if (!CollectionUtils.isEmpty(authRoleList)){
                authRoleList.forEach(role -> {
                    RoleView roleView = new RoleView();
                    roleView.setId(role.getId());
                    roleView.setName(role.getName());
                    roleViews.add(roleView);
                    localUserView.setRoles(role.getName());
                });
            }
        }
        //根据角色查询菜单列表
        List<RoleMenu> authRoleMenuList = authRoleMenuRepository.findAuthRoleMenunByRoleid(roleViews.get(0).getId());
        //根据菜单列表查询一级菜单和二级菜单
        if (!CollectionUtils.isEmpty(authRoleMenuList)){
            List<Long> menuIdList=  authRoleMenuList.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
            /*Map<String,Object> map = new HashMap<>();
            map.put("menuIdList",menuIdList);*/
            //一级菜单
            List<Menu> authMenuList = authMenuRepository.findAuthMenuList(menuIdList);
            if (!CollectionUtils.isEmpty(authMenuList)){
                List<AuthMenuVo> authMenuVoList = new ArrayList<>();
                for (Menu authMenu : authMenuList) {
                    AuthMenuVo menu = new AuthMenuVo();
                    BeanUtils.copyProperties(authMenu, menu);
                    authMenuVoList.add(menu);
                }
                //设置一级菜单
                localUserView.setMenus(authMenuVoList);
                for (AuthMenuVo authMenuVo : localUserView.getMenus()){
                    List<Menu> sonList = authMenuRepository.findAuthMenuListByParentId(authMenuVo.getId());
                    if (!CollectionUtils.isEmpty(sonList)){
                        List<AuthMenuVo> authMenuVoSonList = new ArrayList<>();
                        for (Menu authMenu : sonList) {
                            AuthMenuVo menu = new AuthMenuVo();
                            BeanUtils.copyProperties(authMenu, menu);
                            authMenuVoSonList.add(menu);
                        }
                        //设置二级菜单
                        authMenuVo.setChildren(authMenuVoSonList);
                        for (AuthMenuVo son2 : authMenuVoSonList){
                            List<Menu> sonsonList = authMenuRepository.findAuthMenuListByParentId(son2.getId());
                            if (!CollectionUtils.isEmpty(sonsonList)) {
                                List<AuthMenuVo> authMenuVoSon3List = new ArrayList<>();
                                for (Menu authMenu : sonsonList) {
                                    AuthMenuVo menu = new AuthMenuVo();
                                    BeanUtils.copyProperties(authMenu, menu);
                                    authMenuVoSon3List.add(menu);
                                }
                                //设置三级菜单
                                son2.setChildren(authMenuVoSon3List);
                            }
                        }
                    }
                }
            }
        }
        return Result.ok(localUserView);
    }
    public Result<LoginView> login1(String username, String password) {
        LoginView loginView = new LoginView();
        String encodePwd = DigestUtils.md5Hex(password);
        LocalUser localUser = this.localUserRepository.findByUsernameAndPassword(username, encodePwd);
        if (null == localUser) {
            return Result.failed(1001,"账号或密码错误");
        }
        List<Role> roles = this.authRoleRepository.findByUserId(localUser.getId());
        List<UserSessionView.RoleView> roleViews = new ArrayList<>();
        roles.forEach(role -> {
            UserSessionView.RoleView roleView = new UserSessionView.RoleView();
            roleView.setId(role.getId());
            roleView.setName(role.getName());
            roleViews.add(roleView);
        });
        UserSessionView view = new UserSessionView(localUser.getId(), roleViews);
        view.putExtendValue("iconPath", localUser.getIconPath());
        view.putExtendValue("username", localUser.getUsername());
        Long[] longs = (Long[])roleViews.stream().map(UserSessionView.RoleView::getId).distinct().toArray(x$0 -> new Long[x$0]);
        Result menuResult= this.menuService.findTreeMenuByRoleIdIn(longs);
        view = this.sessionManager.saveUserSession(view);
        loginView.setToken(view.getToken());
        loginView.setMenus((List<MenuTreeView>) menuResult.getData());
        loginView.setUserInfo(localUser);
        return Result.ok(loginView);
    }

    public QueryResults<LocalUserView> pageLocalUser(String username, int pageNum, int pageSize) {
        QLocalUser qLocalUser = QLocalUser.localUser;
        BooleanBuilder builder = new BooleanBuilder();
        if (StringUtils.isNotBlank(username)){
            builder.and(qLocalUser.username.eq(username));
        }
        QueryResults<LocalUserView> localUserViewQueryResults = queryFactory.select(
                Projections.bean(
                        LocalUserView.class,
                        qLocalUser.id,
                        qLocalUser.username,
                        qLocalUser.fUserId,
                        qLocalUser.remark,
                        qLocalUser.createTime,
                        qLocalUser.iconPath,
                        qLocalUser.password
                )
        ).from(qLocalUser)
                .where(builder).offset(pageNum * pageSize).limit(pageSize).fetchResults();
        //对分页结果进行处理
        List<LocalUserView> results = localUserViewQueryResults.getResults();
        // 创建一个用于存储修改后元组对象的列表
        List<LocalUserView> modifiedResults = new ArrayList<>();
        for (LocalUserView localUserView : results) {
            String role = authUserRoleRepository.queryRole(localUserView.getUserId());
            localUserView.setRoles(role);
            // 将修改后的元组对象添加到列表中
            modifiedResults.add(localUserView);
        }
        // 创建一个新的QueryResults对象，包含修改后的分页记录
        QueryResults<LocalUserView> modifiedQueryResults = new QueryResults<>(
                modifiedResults,
                localUserViewQueryResults.getTotal(),
                localUserViewQueryResults.getOffset(),
                localUserViewQueryResults.getLimit()
        );
        return modifiedQueryResults;
    }
    @Transactional(rollbackFor = {Exception.class})
    public Result<LocalUser> saveLocalUser(LocalUserModel model) {
        LocalUser localUser = this.localUserRepository.findOneByUsername(model.getUsername());
        if (null != localUser) {
            return Result.failed(2001,"用户名重复");
        }
        if (!model.getPassword().equals(model.getConfirmPassword())) {
            return Result.failed(2002,"两次输入密码不一致");
        }
        Result userResult = this.userService.registerUser(new UserRegisterModel());
        localUser = new LocalUser();
        BeanUtils.copyProperties(model, localUser);
        //id和user_id都使用auth_user表生成的id
        localUser.setId((Long)userResult.getData());
        localUser.setfUserId((Long)userResult.getData());
        localUser.setPassword(DigestUtils.md5Hex(model.getPassword()));
        this.localUserRepository.save(localUser);
        if (!CollectionUtils.isEmpty(model.getRoles())) {
            this.userRoleService.saveUserRole(new UserRoleModel(localUser.getfUserId(), model.getRoles()));
        }
        return Result.ok(localUser);
    }



}